package com.elitesland.metadata.service.impl;

import com.elitesland.core.base.PagingVO;
import com.elitesland.core.exception.BusinessException;
import com.elitesland.metadata.convert.MetaColumnConvert;
import com.elitesland.metadata.entity.MetaColumnDO;
import com.elitesland.metadata.entity.QMetaColumnDO;
import com.elitesland.metadata.param.MetaColumnQParam;
import com.elitesland.metadata.repo.MetaColumnRepo;
import com.elitesland.metadata.service.MetaColumnService;
import com.elitesland.metadata.service.MetaFieldService;
import com.elitesland.metadata.service.MetaTableService;
import com.elitesland.metadata.vo.MetaColumnVO;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * <pre>作用说明</pre>
 *
 * @author mir
 * @date 11/21/2020 6:12 PM
 */
@Service
public class MetaColumnServiceImpl implements MetaColumnService {

    private MetaColumnRepo metaColumnRepo;

    private MetaFieldService metaFieldService;

    private MetaTableService metaTableService;

    @Autowired
    public void setMetaColumnRepo(MetaColumnRepo metaColumnRepo) {
        this.metaColumnRepo = metaColumnRepo;
    }

    @Autowired
    public void setMetaTableService(MetaTableService metaTableService) {
        this.metaTableService = metaTableService;
    }

    @Autowired
    public void setMetaFieldService(MetaFieldService metaFieldService) {
        this.metaFieldService = metaFieldService;
    }

    private final QMetaColumnDO columns = QMetaColumnDO.metaColumnDO;

    @Override
    public CompletableFuture<PagingVO<MetaColumnVO>> search(Long tableId, MetaColumnQParam param) {
        Predicate predicate = columns.tableId.eq(tableId);

        predicate = StringUtils.isBlank(param.getFieldCode()) ? predicate :
                ExpressionUtils.and(predicate, columns.fieldCode.like("%" + param.getFieldCode() + "%"));

        //todo: 添加查询条件

        final Predicate finalPredicate = predicate;
        return CompletableFuture.supplyAsync(() -> {
            val ret = metaColumnRepo.findAll(finalPredicate, param.getPageRequest());

            return PagingVO.<MetaColumnVO>builder()
                    .total(ret.getTotalElements())
                    .records(ret.getContent().stream().map(MetaColumnConvert.INSTANCE::doToVO)
                            .collect(Collectors.toList()))
                    .build();
        });
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void addColumns(Long tableId, List<MetaColumnVO> columns) {
        val tableOpt = metaTableService.oneById(tableId);
        if (tableOpt.isEmpty()) {
            throw new BusinessException("表定义：" + tableId + "，不存在");
        }
        val table = tableOpt.get();

        val oldCols = metaColumnRepo.findAllByTableId(tableId);

        val newCols = new ArrayList<MetaColumnDO>();
        columns.forEach(c -> {
            oldCols.forEach(oc -> {
                if (c.getId().equals(oc.getId())) {
                    oc.setUdcDomainCode(c.getUdcDomainCode())
                            .setUdcCode(c.getUdcCode())
                            .setUdcDefaultDesc(c.getUdcDesc())
                            .setPageLabel(c.getPageLabel())
                            .setPageElement(c.getPageElement())
                            .setMobileLabel(c.getMobileLabel())
                            .setMobileElement(c.getMobileElement());
                } else {
                    newCols.add(MetaColumnConvert.INSTANCE.voToDO(c));
                }
            });
        });
        newCols.addAll(oldCols);
        metaColumnRepo.saveAll(newCols);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void removeColumns(Long tableId, List<Long> fieldIds) {
        metaColumnRepo.deleteAllByTableIdAndFieldIdIn(tableId, fieldIds);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void removeColumnsByTableId(Long tableId) {
        metaColumnRepo.deleteAllByTableId(tableId);
    }
}
